package com.hyhy.hycloud.commons.support;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.elasticsearch.client.Client;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.*;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.EntityMapper;
import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
import org.springframework.data.elasticsearch.core.geo.CustomGeoModule;
import org.springframework.util.StringUtils;

import java.io.IOException;

/**
 * @author lanpengfei
 * @date 2018/12/24
 */
@Configuration
@ConditionalOnClass(Client.class)
@Conditional(ElasticsearchTemplateConfig.ClusterNodesCondition.class)
public class ElasticsearchTemplateConfig {
    @Autowired
    private ObjectMapper objectMapper;

    @Bean
    public ElasticsearchTemplate elasticsearchTemplate(Client client, ElasticsearchConverter converter) {
        return new ElasticsearchTemplate(client, converter, new EntityMapper() {
            @Override
            public String mapToString(Object o) throws IOException {
                ObjectMapper esObjectMapper = objectMapper.copy();
                esObjectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
                esObjectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
                esObjectMapper.registerModule(new CustomGeoModule());
                return esObjectMapper.writeValueAsString(o);
            }

            @Override
            public <T> T mapToObject(String s, Class<T> aClass) throws IOException {
                ObjectMapper esObjectMapper = objectMapper.copy();
                esObjectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
                esObjectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
                esObjectMapper.registerModule(new CustomGeoModule());
                return esObjectMapper.readValue(s, aClass);
            }
        });
    }

    public static class ClusterNodesCondition implements Condition {
        @Override
        public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
            return !StringUtils.isEmpty(conditionContext.getEnvironment().getProperty("spring.data.elasticsearch.cluster-nodes"));
        }
    }
}
